package com.tramp.utils;

import java.lang.reflect.Field;
import java.util.List;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.type.classreading.CachingMetadataReaderFactory;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.core.type.filter.AssignableTypeFilter;
import org.springframework.util.AntPathMatcher;

import com.google.common.collect.Lists;
import com.tramp.frame.server.base.EnumParam;

/**
 * @since 2016/11/24
 */
public final class ClassUtil {
	private static final Logger LOGGER = LoggerFactory.getLogger(ClassUtil.class);

	private ClassUtil() {
	}

	/**
	 * 取得某个接口下所有实现这个接口的类
	 * */
	public static List<Class> getAllClassByInterface(List<String> packageNames) {
		List<Class> returnClassList = Lists.newArrayList();
		try {
			AssignableTypeFilter filter = new AssignableTypeFilter(EnumParam.class);
			PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();
			resolver.setPathMatcher(new AntPathMatcher());
			for (String packageName : packageNames) {
				Resource[] resources = resolver
						.getResources(PathMatchingResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + packageName.replaceAll("\\.", "/") + "/*.class");
				MetadataReaderFactory readerFactory = new CachingMetadataReaderFactory(resolver);
				String interfaceName = EnumParam.class.getName();
				for (Resource resource : resources) {
					MetadataReader reader = readerFactory.getMetadataReader(resource);
					if (filter.match(reader, readerFactory)) {
						String className = resource.getFilename().substring(0, resource.getFilename().length() - 6);
						if (!className.equals(interfaceName.substring(interfaceName.lastIndexOf(".") + 1))) {
							returnClassList.add(Class.forName(packageName + "." + className));
						}
					}
				}
			}
		}
		catch (Exception e) {
			LOGGER.error("getAllClassByInterface error", e);
		}
		return returnClassList;
	}

	/**
	 * 设置类中某个属性的值，(类没有提供set方法)
	 * @param obj
	 * @param fieldName
	 * @param value
	 * @throws IllegalAccessException
	 * @throws NoSuchFieldException
	 */
	public static void setValueByFieldName(Object obj, String fieldName, Object value) throws IllegalAccessException, NoSuchFieldException {
		Field field = obj.getClass().getDeclaredField(fieldName);
		if (field.isAccessible()) {
			field.set(obj, value);
		}
		else {
			field.setAccessible(true);
			field.set(obj, value);
			field.setAccessible(false);
		}
	}

	/**
	 *
	 * @param obj
	 * @param fieldName
	 * @return
	 */
	public static Field getFieldByFieldName(Object obj, String fieldName) {
		for (Class<?> superClass = obj.getClass(); superClass != Object.class; superClass = superClass.getSuperclass()) {
			try {
				return superClass.getDeclaredField(fieldName);
			}
			catch (NoSuchFieldException e) {
				//正常逻辑，无需处理
			}
		}
		return null;
	}

	/**
	 * 获取类中某个属性的值，(类没有提供get方法)
	 * @param obj
	 * @param fieldName
	 * @return
	 * @throws IllegalAccessException
	 */
	public static Object getValueByFieldName(Object obj, String fieldName) throws IllegalAccessException {
		Field field = getFieldByFieldName(obj, fieldName);
		Object value = null;
		if (field != null) {
			if (field.isAccessible()) {
				value = field.get(obj);
			}
			else {
				field.setAccessible(true);
				value = field.get(obj);
				field.setAccessible(false);
			}
		}
		return value;
	}
}
